from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render_to_response
from django.contrib.auth import *
from django.contrib.auth.decorators import login_required, permission_required
from django.template import RequestContext

from models import *
from settings import *
from forms import *

import os
import simplejson

@login_required(login_url='/login/')
def menu_ppal(request):
    assert(request.user.is_authenticated())
    return render_to_response('menuppal.html', locals(), context_instance=RequestContext(request))


"""
Registrar Usuario
"""
def registrarse(request):
    if request.method == 'POST': # si se envio el form
        form = RegisterForm(request.POST)
        if form.is_valid():
            # proceso los datos del usuario
            u = form.cleaned_data.get('usuario')
            n = form.cleaned_data.get('nombreParaJugar')
            e = form.cleaned_data.get('email')
            p = form.cleaned_data.get('contrasenia')
            usuario = Usuario.objects.create_user(u, e, p)
            usuario.nombreParaJugar = n
            usuario.save()
            usuario = authenticate(username=u, password=p)
            if usuario is not None and usuario.is_active:
                login(request, usuario)
            return HttpResponseRedirect('/bienvenido/')
    else:
            form = RegisterForm() # Un form unbound
    return render_to_response('registrarse.html', locals(), context_instance=RequestContext(request))

"""
Pantalla de bienvenida
"""
@login_required(login_url='/login/')
def bienvenido(request):
    return render_to_response('bienvenido.html', locals(), context_instance=RequestContext(request))

"""
Reglas del juego
"""
@login_required(login_url='/login/')
def reglamento(request):
    return render_to_response('reglamento.html', locals(), context_instance=RequestContext(request))


"""
Unirse
"""
@login_required(login_url='/login/')
def unirse(request):
    if request.method == 'POST': # si se envio el form
        form = NewUnirseForm(request.POST)
        if form.is_valid():
            partidaSeleccionada = form.cleaned_data['partidas']

            jugador = Jugador(color = form.cleaned_data['colorEjercitos'], 
                              estadoTurno = '', 
                              ordenEnPartida = 0, 
                              ejercitosDisp = 0, 
                              usuario = request.user, 
                              partidaActual = partidaSeleccionada)
            jugador.save()

            return HttpResponseRedirect('/esperarJugadores/')
    else:
        partidas = Partida.objects.filter(estado="Inactiva")
        form = NewUnirseForm()
    return render_to_response('unirse.html', locals(), context_instance=RequestContext(request))


"""
Crear nuevo juego
"""
@login_required(login_url='/login')
def crearPartida(request):
    if request.method == 'POST': # si se envio el form
        form = NewGameForm(request.POST)

        if form.is_valid():
            num_jugadores = form.cleaned_data['cantidadJugadores']
            num_bots = form.cleaned_data['cantidadBots']
        
            lugares_disponibles = num_jugadores - num_bots - 1
            partida = Partida(nombre = form.cleaned_data['nombrePartida'], 
                              estado = 'Inactiva', 
                              jugadorActual = None, 
                              lugaresDisponibles = lugares_disponibles, 
                              mapa = form.cleaned_data['mapa'])
            partida.save()
            
            jugador = Jugador(color = form.cleaned_data['colorEjercitos'], 
                              estadoTurno = '', 
                              ordenEnPartida = 0, 
                              ejercitosDisp = 0, 
                              usuario = request.user, 
                              partidaActual = partida)
            jugador.save()
            
            if lugares_disponibles == 0: # el usuario quiere jugar solo con bots
                return HttpResponseRedirect('/iniciarPartida/')
            else:
                return HttpResponseRedirect('/esperarJugadores/')
    else:
            form = NewGameForm() # Un form unbound

    # La vista previa necesita asociar ids a URLs de los mapas. Le generamos
    # una tabla y se la pasamos con JSON
    mapas = Mapa.objects.filter(usable=True)
    mapasjs = {}
    for m in mapas:
        mapasjs[m.id] = m.imagen.url
    mapasjs = simplejson.dumps(mapasjs)

    return render_to_response('crearpartida.html', locals(), context_instance=RequestContext(request))


"""
Esperar Jugadores
"""
def esperarJugadores(request):
    partida = (request.user).jugador_set.get().partidaActual
    
    lista_aux = [None]
    lista_lugares_disp = lista_aux * partida.lugaresDisponibles
    return render_to_response('esperarJugadores.html', locals(), context_instance=RequestContext(request))


"""
Iniciar Partida
"""
@login_required(login_url='/login')
def vistaPartida(request,nombrePartida=""):
    if not nombrePartida:
        return HttpResponseRedirect('/menu/')  # Error en nombre de partida
    partidaDB= Partida.objects.get(nombre=nombrePartida)
    jugadorDB = Jugador.objects.get(usuario=request.user)

    if jugadorDB not in (Jugador.objects.filter(partidaActual=partidaDB)):
        return HttpResponseRedirect('/GO AWAY!')

    if partidaDB.estado == "Esperando":
        return HttpResponseRedirect('/esperandoJugadores')

    elif partidaDB.estado == "Iniciando":
        if jugadorDB.estadoTurno == "Activo":
            # form is valid
             incorporar = True
        else:
             esperar = True

    elif partidaDB.estado == "Activa":
        if jugadorDB.estadoTurno == "Activo" and "incorporar":  ### ...
            # form is valid ...
            incorporar = True
        elif jugadorDB.estadoTurno == "Activo" and "atacar":
            # form is valid ...
            atacar = True
        elif jugadorDB.estadoTurno == "Activo" and "reagrupar":
            # form is valid ...
            reagrupar = True
        elif jugadorDB.estadoTurno == "Inactivo":
            esperar = True

    else:
        finalizada = True

## dibuja la pantalla de partida segun los boolean pasados... (y estado extra)
    return render_to_response('partida.html', locals(), context_instance=RequestContext(request))










"""Editar un mapa de la base de datos"""
@permission_required('request.user.is_staff')
def editarMapa(request):
    if request.method == 'POST': # Si se envio el form
        form = EditMapForm(request.POST)
        if form.is_valid():
            mapa = form.cleaned_data.get('mapa').nombre
            # Procedo a editar el mapa:
            return HttpResponseRedirect('/crearmapa/' + mapa)
    else:
            form = EditMapForm() # Formulario vacio

    mapas = Mapa.objects.all()
    previews = {} # Diccionario con previews de cada mapa
    for m in mapas:
        previews[m.id] = m.imagen.url # Entradas ('mapa_id': 'URL_imagen')
    sizeList = len(mapas)

    return render_to_response('editarmapa.html', locals(), context_instance=RequestContext(request))


"""Crear Mapa"""
@permission_required('request.user.is_staff')
def crearMapa(request, mapa=''):
    listaMapas = (Mapa.objects.filter(nombre=mapa))
    if not listaMapas: # El mapa no existe
        return HttpResponseRedirect('/crearmapa/')
    assert(len(listaMapas) == 1) # No deberia haber mapas duplicados
    mapaDB = listaMapas[0]

    if request.method == 'POST': # Si se envio el form
        form = NewCountryForm(request.POST)

        if form.is_valid():
            p = form.cleaned_data.get('nombrePais')
            c = form.cleaned_data.get('continente')
            x = form.cleaned_data.get('pos_x')
            y = form.cleaned_data.get('pos_y')

            pais = Pais(nombre=p, continente=c, coordX=x, coordY=y, mapaAsoc=mapaDB)

            # Impedir que se agregue un pais que ya existe en el mapa...
            if not Pais.objects.filter(mapaAsoc=mapaDB, nombre=p):
                pais.save()

    else:
        form = NewCountryForm() # Formulario vacio

    # Me ubico en la parte del template que corresponde:
    imagen_elegida = True
    edit_vecinos = False

    # Obtengo la ruta de la imagen a partir de los datos de la BD:
    imagen = 'mapas/' + os.path.split(mapaDB.imagen.name)[1]

    # Obtengo los paises asociados al mapa que estoy editando:
    listaPaises = Pais.objects.filter(mapaAsoc=mapaDB)
    cincuentapaises = len(listaPaises) >= 50

    return render_to_response('crearmapa.html', locals(), context_instance=RequestContext(request))


"""Borrar pais y volver a la edicion del mapa"""
@permission_required('request.user.is_staff')
def borrarPais(request, mapa='', pais=''):
    mapaDB = get_mapa_from_db(mapa)

    Pais.objects.filter(mapaAsoc=mapaDB, nombre=pais).delete()

    return HttpResponseRedirect('/crearmapa/'+mapa)

"""Habilitar un mapa para jugar (solo si es conexo)"""
@permission_required('request.user.is_staff')
def guardarMapa(request, mapa=''):
    mapaDB = get_mapa_from_db(mapa)
    if es_conexo(mapaDB):
        mapaDB.usable = True
        mapaDB.save()
    else:
        # El mapa no es conexo:
        mapaDB.usable = False
        mapaDB.save()
        return HttpResponseRedirect('/crearmapa/'+mapa)

    return HttpResponseRedirect('/menu')


"""Borrar el mapa de la base de datos"""
@permission_required('request.user.is_staff')
def borrarMapa(request, mapa=''):
    mapaDB = get_mapa_from_db(mapa)
    path = mapaDB.imagen.path
    try:
        # Quitar la imagen de la carpeta de mapas:
        os.remove(path)
    except OSError:
        pass
    # Borrar el mapa de la BD
    mapaDB.delete()

    return HttpResponseRedirect('/menu')


"""Edicion de la lista de vecinos de un pais"""
@permission_required('request.user.is_staff')
def editarVecinos(request, mapa='', pais=''):
    # Obtengo el mapa y el pais de la BD:
    mapaDB = get_mapa_from_db(mapa)
    paisDB = get_pais_from_db(pais, mapaDB)

    if request.method == 'POST': # Si se envio el form
        form = VecinosForm(request.POST)
        #import pdb; pdb.set_trace()
        if form.is_valid():
            # Asocio los vecinos al pais y guardo los cambios:
            vecinos = form.cleaned_data.get('adyacentes')
            paisDB.adyacentes = vecinos
            paisDB.save()

            # Sigo con la edicion del mapa
            return HttpResponseRedirect('/crearmapa/'+mapa)

    else:
        form = VecinosForm() # Formulario vacio

    # Me ubico en la parte del template que corresponde:
    imagen_elegida = True
    edit_vecinos = True

    # Obtengo la ruta de la imagen a partir de los datos de la BD:
    imagen = 'mapas/' + os.path.split(mapaDB.imagen.name)[1]

    # Obtengo los paises asociados al mapa que estoy editando:
    listaPaises = Pais.objects.filter(mapaAsoc=mapaDB)
    vecinos = paisDB.adyacentes.all()

    return render_to_response('crearmapa.html', locals(), context_instance=RequestContext(request))


"""Elegir imagen para el nuevo mapa"""
@permission_required('request.user.is_staff')
def elegirImagen(request):
    if request.method == 'POST': # Si se envio el form
        form = NewMapImageForm(request.POST, request.FILES)

        if form.is_valid():
            # Creo un nuevo mapa en la BD:
            n = form.cleaned_data.get('nombreMapa')
            img = form.cleaned_data.get('imagen')

            mapa = Mapa(nombre=n, imagen=img, usable=False)
            mapa.save()

            # Procedo a editar el mapa recien creado:
            return HttpResponseRedirect('/crearmapa/'+nombreMapa)

    else:
        form = NewMapImageForm() # Formulario vacio

    # Me ubico en la parte del template que corresponde:
    imagen_elegida = False

    return render_to_response('crearmapa.html', locals(), context_instance=RequestContext(request))


"""Funcion que obtiene un mapa de la BD o lanza una excepcion"""
def get_mapa_from_db(mapa):
    listaMapas = (Mapa.objects.filter(nombre=mapa))
    if not listaMapas: # El mapa no existe
        raise forms.ValidationError(u"El mapa no existe")
    assert(len(listaMapas) == 1) # No deberia haber mapas duplicados
    return listaMapas[0]


"""Funcion que obtiene un pais de la BD o lanza una excepcion"""
def get_pais_from_db(pais, mapaDB):
    listaPaises = (Pais.objects.filter(nombre=pais, mapaAsoc=mapaDB))
    if not listaPaises: # El mapa no existe
        raise forms.ValidationError(u"El pais no existe")
    assert(len(listaPaises) == 1) # No deberia haber mapas duplicados
    return listaPaises[0]


"""Funcion que comprueba que el mapa sea conexo"""
def es_conexo(mapaDB):
    paisesDelMapa = Pais.objects.filter(mapaAsoc=mapaDB)
    assert(len(paisesDelMapa))
    paisesConectados = [paisesDelMapa[0]]
    i = 0
    while i < len(paisesConectados):
        #import pdb; pdb.set_trace()
        vecinos = paisesConectados[i].adyacentes.all()
        for v in vecinos:
            if v not in paisesConectados:
                paisesConectados.append(v)
        i = i+1

    return len(paisesDelMapa) == len(paisesConectados)

#import pdb; pdb.set_trace()
#django debug toolbar
#insert into modelo_usuario(nombreParaJugar) values('siteg');
